package com.foolishbird.sdk.utils;

import android.Manifest;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Process;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class AndroidDeviceGenerator {

    private static final String READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE;

    private static final String DEVICE_UUID_FILE = "device_uuid_info";
    private static final String DEVICE_UUID_KEY = "uuid";

    public static final String UNKNOWN = "unknown";


    private AndroidDeviceGenerator() {

    }

    /**
     * 生成安卓设备UUID
     *
     * @return 返回安卓设备的UUID
     */
    public static String generateAndroidDeviceUUID(Context context) {
        if (context == null) {
            throw new NullPointerException("context instance is null.");
        }

        String deviceUUID;

        synchronized (AndroidDeviceGenerator.class) {
            final SharedPreferences sharedPrefs = context.getSharedPreferences(DEVICE_UUID_FILE, Context.MODE_PRIVATE);
            deviceUUID = sharedPrefs.getString(DEVICE_UUID_KEY, "");
            if (TextUtils.isEmpty(deviceUUID)) {
                StringBuilder builder = new StringBuilder();
                builder.append(getAndroidId(context)).append(File.separator);
                builder.append(getAndroidDeviceId(context)).append(File.separator);
                builder.append(getAndroidSerialNumber(context)).append(File.separator);
                builder.append(getAndroidDeviceName()).append(File.separator);
                builder.append(getAndroidDeviceBrand()).append(File.separator);
                builder.append(getAndroidDeviceModel()).append(File.separator);
                builder.append(getAndroidDeviceManufacturer());

                deviceUUID = UUID.nameUUIDFromBytes(builder.toString().getBytes(Charset.defaultCharset())).toString();

                if (TextUtils.isEmpty(deviceUUID)) {
                    deviceUUID = UUID.randomUUID().toString();
                }

                sharedPrefs.edit().putString(DEVICE_UUID_KEY, deviceUUID).apply();
            }
        }

        return deviceUUID;
    }

    /**
     * 获取安卓设备序列号，设备系统被重置，可能会发生改变
     *
     * @param context APP应用上下文context
     * @return 返回安卓设备序列号
     */
    public static String getAndroidSerialNumber(Context context) {
        String serial = UNKNOWN;

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
            serial = Build.SERIAL;
        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            if (checkReadPhoneStatePermission(context)) {
                serial = Build.getSerial();
            }
        } else {
            serial = getAndroidId(context);
        }

        return serial;
    }

    /**
     * 获取安卓移动电话设备ID，非移动电话设备可能为空/unknown
     *
     * @param context APP应用上下文context
     * @return 返回安卓移动电话设备ID
     */
    public static String getAndroidDeviceId(Context context) {
        String deviceId = UNKNOWN;

        if (checkReadPhoneStatePermission(context)) {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
                deviceId = tm != null ? tm.getDeviceId() : UNKNOWN;
            } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                deviceId = tm != null ? tm.getImei() : UNKNOWN;
            }
        }

        return deviceId;
    }

    /**
     * 获取安卓设备ANDROID_ID
     *
     * @param context APP应用上下文context
     * @return 返回安卓设备ANDROID_ID
     */
    public static String getAndroidId(Context context) {
        return Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
    }

    /**
     * 获取安卓设备型号
     *
     * @return 返回安卓设备型号
     */
    public static String getAndroidDeviceModel() {
        return Build.MODEL;
    }

    /**
     * 获取安卓设备品牌
     *
     * @return 返回安卓设备品牌
     */
    public static String getAndroidDeviceBrand() {
        return Build.BRAND;
    }

    /**
     * 获取安卓设备名称
     *
     * @return 返回安卓设备名称
     */
    public static String getAndroidDeviceName() {
        return Build.DEVICE;
    }

    /**
     * 获取安卓设备的制造商名称
     *
     * @return 返回安卓设备制造商的名称
     */
    public static String getAndroidDeviceManufacturer() {
        return Build.MANUFACTURER;
    }

    /**
     * 获取移动电话设备运营商名称
     *
     * @param context 上下文context
     * @return 返回移动电话设备运营商名称
     */
    public static String getSimOperatorName(Context context) {
        if (checkReadPhoneStatePermission(context)) {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            return tm.getSimOperatorName();
        }
        return UNKNOWN;
    }

    /**
     * 获取移动电话设备SIM卡的IMSI码
     *
     * @param context 上下文context
     * @return 返回移动电话设备SIM卡的IMSI码
     */
    public static String getSubscriberId(Context context) {
        if (checkReadPhoneStatePermission(context)) {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                return tm.getSubscriberId();
            } else {
                return getAndroidId(context);
            }
        }
        return UNKNOWN;
    }

    /**
     * 获取移动电话设备SIM卡的IMSI码
     *
     * @param context 上下文context
     * @return 返回移动电话设备SIM卡的IMSI码
     */
    public static String getLine1Number(Context context) {
        if (checkReadPhoneStatePermission(context)) {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            String line1Number="";
            try {
                line1Number = tm.getLine1Number();
            }catch (Exception e){
                e.printStackTrace();
            }
            if(!TextUtils.isEmpty(line1Number)){
                Pattern pattern = Pattern.compile( "1[2|3|4|5|6|7|8|9][0-9]{9}$" );
                Matcher matcher = pattern.matcher(line1Number);
                StringBuffer buffer = new StringBuffer();
                if (matcher.find()) {
                    buffer.append(matcher.group());
                }
                return buffer.toString();
            }
        }
        return UNKNOWN;
    }

    /**
     * 检查电话权限是否被授权
     *
     * @param context 上下文context
     * @return 如果被授权了电话权限，返回true，否则，返回false
     */
    public static boolean checkReadPhoneStatePermission(Context context) {
        return PackageManager.PERMISSION_GRANTED == context.checkPermission(READ_PHONE_STATE, Process.myPid(), Process.myUid());
    }

    /**
     * 生成16位AES随机密钥
     *
     * @return
     */
    private static String getAESRandomKey() {
        long longValue = new Random().nextLong();
        return String.format("%016x", longValue);
    }


    protected static String uuid;

    public static String getDeviceID(Context context) {
        if (uuid == null) {
            generateDeviceID(context);
        }
        return uuid;
    }

    public static void generateDeviceID(Context context) {

        if (uuid == null) {
            synchronized (AndroidDeviceGenerator.class) {
                if (uuid == null) {
                    final SharedPreferences prefs = context.getSharedPreferences("g_device_id.xml", 0);
                    final String id = prefs.getString("device_id", null);

                    if (id != null) {
                        // Use the ids previously computed and stored in the prefs file
                        uuid = id;
                    } else {
                        final String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);

                        // Use the Android ID unless it's broken, in which case fallback on deviceId,
                        // unless it's not available, then fallback on a random number which we store
                        // to a prefs file
                        try {
                            if (!"9774d56d682e549c".equals(androidId)) {
                                uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8")).toString();
                            } else {
                                uuid = UUID.randomUUID().toString();
                            }
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }

                        // Write the value out to the prefs file
                        prefs.edit().putString("device_id", uuid.toString()).commit();

                    }
                }
            }
        }

    }
}
